package cn.ug.pay.service.impl;

import cn.ug.bean.LoginBean;
import cn.ug.bean.base.DataTable;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.FundRateConfig;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.core.login.LoginHelper;
import cn.ug.enums.RateKeyEnum;
import cn.ug.feign.RateSettingsService;
import cn.ug.pay.bean.TransferAccountsBean;
import cn.ug.pay.bean.TransferAccountsQueryBean;
import cn.ug.pay.bean.TransferAccountsResultBean;
import cn.ug.pay.bean.status.CommonConstants;
import cn.ug.pay.bean.status.PayDistributePrefix;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.pay.mapper.BillMapper;
import cn.ug.pay.mapper.PayTransferAccountsMapper;
import cn.ug.pay.mapper.entity.PayTransferAccounts;
import cn.ug.pay.mapper.entity.TransferAccounts;
import cn.ug.pay.service.MemberAccountService;
import cn.ug.pay.service.TransferAccountsService;
import cn.ug.util.DateUtils;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Author zhangweijie
 * @Date 2019/7/22 0022
 * @time 下午 17:49
 **/
@Service
public class TransferAccountsServiceImpl implements TransferAccountsService {

    @Autowired
    private PayTransferAccountsMapper payTransferAccountsMapper;

    @Autowired
    private MemberAccountService memberAccountService;

    @Autowired
    private RateSettingsService rateSettingsService;

    @Autowired
    private BillMapper billMapper;

    @Autowired
    private FundRateConfig fundRateConfig;

    @Resource
    private RedisGlobalLock redisGlobalLock;

    private static Logger logger = LoggerFactory.getLogger(TransferAccountsServiceImpl.class);

    @Override
    public SerializeObject save(TransferAccountsBean transferAccountsBean) {
        //新增
        if (StringUtils.isBlank(transferAccountsBean.getId())) {
            //根据银行卡号和转账单号联合查询单号是否存在  存在不允许重复提交
            Map paramsMap = new HashMap();
            paramsMap.put("transferNumbers", transferAccountsBean.getTransferNumbers());
            paramsMap.put("bankAccount", transferAccountsBean.getBankAccount());
            PayTransferAccounts resultBean = payTransferAccountsMapper.selectByAccountAndNumbers(paramsMap);
            if (resultBean != null) {
                return new SerializeObjectError("00000004");
            }

            PayTransferAccounts payTransferAccounts = new PayTransferAccounts();
            BeanUtils.copyProperties(transferAccountsBean, payTransferAccounts);
            //审核状态 1:待审核 2:已通过 3:已拒绝
            payTransferAccounts.setAuditStatus(1);
            LoginBean loginBean = LoginHelper.getLoginBean();
            payTransferAccounts.setId(UF.getRandomUUID());
            payTransferAccounts.setCreateUserId(loginBean.getId());  //设置创建用户id
            payTransferAccounts.setCreateUser(loginBean.getName());  //设置创建用户姓名
            payTransferAccounts.setVoucherImg(transferAccountsBean.getVoucherImg());
            payTransferAccounts.setApplyTime(new Date());
            int rows = payTransferAccountsMapper.insertSelective(payTransferAccounts);
            Ensure.that(rows).isLt(1, "00000005");
        } else {
            //修改-重新提交
            PayTransferAccounts payTransferAccounts = payTransferAccountsMapper.selectByPrimaryKey(transferAccountsBean.getId());
            if (payTransferAccounts == null) {
                return new SerializeObjectError("00000003");
            }
            BeanUtils.copyProperties(transferAccountsBean, payTransferAccounts);
            //审核状态 1:待审核 2:已通过 3:已拒绝
            payTransferAccounts.setAuditStatus(1);
            LoginBean loginBean = LoginHelper.getLoginBean();
            payTransferAccounts.setCreateUserId(loginBean.getId());  //设置创建用户id
            payTransferAccounts.setCreateUser(loginBean.getName());  //设置创建用户姓名
            payTransferAccounts.setVoucherImg(transferAccountsBean.getVoucherImg());
            payTransferAccounts.setApplyTime(new Date());
            int rows = payTransferAccountsMapper.updateByPrimaryKeySelective(payTransferAccounts);
            Ensure.that(rows).isLt(1, "00000005");
        }
        return new SerializeObject<>(ResultType.NORMAL);
    }

    @Override
    public DataTable<TransferAccountsResultBean> queryList(TransferAccountsQueryBean transferAccountsQueryBean) {
        Page<TransferAccounts> page = PageHelper.startPage(transferAccountsQueryBean.getPageNum(), transferAccountsQueryBean.getPageSize());
        String jsonStr = JSONObject.toJSONString(transferAccountsQueryBean);
        Map paramsMap = (Map) JSONObject.parse(jsonStr);
        List<TransferAccounts> transferAccountsList = payTransferAccountsMapper.queryList(paramsMap);
        List<TransferAccountsResultBean> resultBeanList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(transferAccountsList)) {
            for (TransferAccounts transferAccounts : transferAccountsList) {
                TransferAccountsResultBean transferAccountsResultBean = new TransferAccountsResultBean();
                BeanUtils.copyProperties(transferAccounts, transferAccountsResultBean);
                transferAccountsResultBean.setAddTime(DateUtils.dateToStr(transferAccounts.getAddTime(), DateUtils.patter));
                transferAccountsResultBean.setModifyTime(DateUtils.dateToStr(transferAccounts.getModifyTime(), DateUtils.patter));
                transferAccountsResultBean.setApplyTime(DateUtils.dateToStr(transferAccounts.getApplyTime(), DateUtils.patter));
                if (transferAccounts.getAuditTime() != null) {
                    transferAccountsResultBean.setAuditTime(DateUtils.dateToStr(transferAccounts.getAuditTime(), DateUtils.patter));
                }
                resultBeanList.add(transferAccountsResultBean);
            }
        }
        return new DataTable<>(page.getPageNum(), page.getPageSize(), page.getTotal(), resultBeanList);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public SerializeObject updateAuditStatus(String id, Integer status, String remark) {
        LoginBean loginBean = LoginHelper.getLoginBean();
        // 1、获取分布式锁防止重复调用 =====================================================
        String key = PayDistributePrefix.LARGE_MONEY_RECHARGE + loginBean.getId() + id;
        if (redisGlobalLock.lock(key)) {
            logger.info("----测试分布式锁-----memberId=" + loginBean.getId() + "---------申请转账id-----" + id + "--------时间=" + UF.getFormatDateTime(LocalDateTime.now()));
            try {
                PayTransferAccounts payTransferAccounts = payTransferAccountsMapper.selectByPrimaryKey(id);
                if (payTransferAccounts == null) {
                    return new SerializeObjectError("00000003");
                }
                //判断是否已经审核通过
                if (payTransferAccounts.getAuditStatus() == 2) {
                    return new SerializeObjectError("170020489");
                }
                //审核通过
                if (status == 2) {
                    SerializeObject rateBean = rateSettingsService.get(RateKeyEnum.RECHARGE.getKey());
                    BigDecimal fee = BigDecimal.ZERO;
                    if (rateBean != null && rateBean.getData() != null) {
                        JSONObject json = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()));
                        int dayNum = billMapper.getTransactionNumForThisDay(payTransferAccounts.getMemberId(), CommonConstants.PayType.RECHARGE.getIndex());
                        int monthNum = billMapper.getTransactionNumForThisMonth(payTransferAccounts.getMemberId(), CommonConstants.PayType.RECHARGE.getIndex());
                        fee = fundRateConfig.getFee(json, payTransferAccounts.getAmount(), dayNum, monthNum);
                    }
                    String result = memberAccountService.largeRecharge(payTransferAccounts.getMemberId(), payTransferAccounts.getAmount(), TradeType.LARGE_AMOUNT_RECHARGE.getValue(), fee);
                    if (StringUtils.isBlank(result))
                        return new SerializeObjectError("00000005");

                } else if (status == 3) {
                    //审核拒绝
                    payTransferAccounts.setRejectRemark(remark);
                }
                payTransferAccounts.setAuditStatus(status);
                payTransferAccounts.setAuditUserId(loginBean.getId());
                payTransferAccounts.setAuditUser(loginBean.getName());
                payTransferAccounts.setAuditTime(new Date());
                int rows = payTransferAccountsMapper.updateByPrimaryKeySelective(payTransferAccounts);
                Ensure.that(rows).isLt(1, "00000005");
                return new SerializeObject<>(ResultType.NORMAL);
            } catch (Exception e) {
                throw e;
            } finally {
                // 4、释放分布式锁 ================================================================
                redisGlobalLock.unlock(key);
            }
        } else {
            // 如果没有获取锁
            Ensure.that(true).isTrue("17000706");
        }
        return null;
    }

    //主要的工具方法
    public byte[] InputStream2ByteArray(String filePath) throws IOException {
        InputStream in = new FileInputStream(filePath);
        byte[] data = toByteArray(in);
        in.close();

        return data;
    }

    public byte[] toByteArray(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        int n = 0;
        while ((n = in.read(buffer)) != -1) {
            out.write(buffer, 0, n);
        }
        return out.toByteArray();
    }
}
